//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ListLigand.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <fstream>

#include <zlib.h>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHTEXT 100
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListLigand::ListLigand () {
  
  this->filenameIn  = new String () ;
  this->filenameOut = new String ();

  this->ligands     = new TListE <Ligand> ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListLigand::ListLigand (const ListLigand& listLigand) {
  
  this->filenameIn  = new String (listLigand.filenameIn) ;
  this->filenameOut = new String (listLigand.filenameOut);

  this->ligands     = new TListE <Ligand> (listLigand.ligands);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListLigand::ListLigand (const ListLigand* listLigand) {
  
  this->filenameIn  = new String (listLigand->filenameIn) ;
  this->filenameOut = new String (listLigand->filenameOut);

  this->ligands     = new TListE <Ligand> (listLigand->ligands);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListLigand::~ListLigand () {

  if (this->filenameIn)  delete this->filenameIn;
  if (this->filenameOut) delete this->filenameOut;

  if (this->ligands)     delete this->ligands;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListLigand::FilenameIn (String* filenameIn) {
  
  if (filenameIn) this->filenameIn->In(filenameIn);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListLigand::FilenameOut (String* filenameOut) {
  
  if (filenameOut) this->filenameOut->In(filenameOut);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ListLigand::Ligands (TListE <Ligand>* ligands) {
  
  if (ligands) *(this->ligands) = *(ligands);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListLigand::FilenameIn (void) {
  
  return this->filenameIn;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ListLigand::FilenameOut (void) {
  
  return this->filenameOut;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <Ligand>* ListLigand::Ligands (void) {
  
  return this->ligands;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListLigand::LoadData (void) {
  
  if (!this->filenameIn || !this->filenameIn->Length()) return false;

  bool isGZFile = (this->filenameIn->Contain("gz"))?1:0;

  fstream file;
  gzFile  zipFile;
  
  char    buffer [LENGTHTEXT + 1];
  
  String* data      = new String ();
  String* line      = new String ();
  String* tmp       = NULL;
  
  int     tmpNumber = 0;

  if (isGZFile) { 
    zipFile = gzopen (this->filenameIn->Out(), "rb9"); 
    if (!zipFile) return false;
  }
  else {
    file.open (this->filenameIn->Out(), fstream::in);
    if (!file.is_open()) return false;
  }

  while (!((isGZFile)?gzeof(zipFile):file.eof())) {
    
    if (isGZFile) gzgets(zipFile, buffer, LENGTHTEXT);
    else          file.getline(buffer, LENGTHTEXT);
    
    if (!strlen(buffer)) continue;

    line->In(buffer);

    tmp = line->SubStr(22, 26);

    if (tmp) { 

      if (!tmpNumber) { 
        data->In("");
        tmpNumber = atoi(tmp->Out()); 
      }

      if (tmpNumber != atoi(tmp->Out())) {

        tmpNumber = atoi(tmp->Out()); 

        Ligand* newLigand = new Ligand ();

        if (newLigand->ReadData(data)) this->ligands->Add(newLigand);
        else                           delete newLigand;

        data->In(line); data->Add("\n");

      }
      else { data->Add(line); data->Add("\n"); }

      delete tmp; 

    }

  }

  Ligand* newLigand = new Ligand ();

  if (newLigand->ReadData(data)) this->ligands->Add(newLigand);
  else                           delete newLigand;

  if (isGZFile) gzclose(zipFile);
  else          file.close();

  if (line) delete line;
  if (data) delete data;

  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ListLigand::DeleteLigandWithLengthLowerThan (int length) {
  
  if (!this->ligands || !this->ligands->Length()) return false;
  
  this->ligands->SetInitial();
  
  while (this->ligands->SetNext()) {
    
    Ligand* currentLigand = this->ligands->GetCurrent();
    
    if (currentLigand->Records()->Length() < length) {
      if (currentLigand == this->ligands->GetFirst()) {
        this->ligands->DestroyCurrent();
        this->ligands->SetInitial();
      }
      else {
        this->ligands->DestroyCurrent();
        this->ligands->SetPrevious();
      }
    }
    
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ListLigand ListLigand::operator= (const ListLigand& listLigand) {
  
  this->filenameIn->In(listLigand.filenameIn) ;
  this->filenameOut->In(listLigand.filenameOut);

  *(this->ligands) = *(listLigand.ligands);
  
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
